package cn.ycc1.functionlibrary.io;

/**
 * Working with Paths
 * @author ycc
 * @date 2025/3/8
 */
public class Working {
    /**
     * Creating a Path
     * Using the Paths Factory Class
     * A Path instance contains the information used to specify the location of a file or directory. At the time it is
     * defined, a Path is provided with a series of one or more names. A root element or a file name might be included,
     * but neither are required. A Path might consist of just a single directory or file name.
     *
     * You can easily create a Path object by using one of the following get methods from the Paths (note the plural) helper
     * class:
     *
     * Path p1 = Paths.get("/tmp/foo");
     * Path p2 = Paths.get(args[0]);
     * Path p3 = Paths.get(URI.create("file:///Users/joe/FileTest.java"));
     * The Paths.get(String) method is shorthand for the following code:
     *
     * Path p4 = FileSystems.getDefault().getPath("/users/sally");
     * The following example creates /u/joe/logs/foo.log assuming your home directory is /u/joe, or C:\joe\logs\foo.log if
     * you are on Windows.
     *
     * Path p5 = Paths.get(System.getProperty("user.home"),"logs", "foo.log");
     * Using the Path.of() Factory methods
     * Two factory methods have been added to the Path interface in Java SE 9.
     *
     * The first method takes a string of characters, denoting the path string or the initial part of the path string.
     * It can take further string of characters as a vararg that are joined to form the path string.
     *
     * The second method takes a URI, which is converted to this path.
     *
     * The following code used the first factory method to create a path.
     *
     * Path debugFile = Path.of("/tmp/debug.log");
     */

    /**
     * Retrieving Information about a Path
     * You can think of the Path as storing these name elements as a sequence. The highest element in the directory structure
     * would be located at index 0. The lowest element in the directory structure would be located at index [n-1], where n is
     * the number of name elements in the Path. Methods are available for retrieving individual elements or a subsequence of
     * the Path using these indexes.
     *
     * The following code snippet defines a Path instance and then invokes several methods to obtain information about the path:
     *
     * // None of these methods requires that the file corresponding
     * // to the Path exists.
     * // Microsoft Windows syntax
     * Path path = Paths.get("C:\\home\\joe\\foo");
     *
     * // Solaris syntax
     * Path path = Paths.get("/home/joe/foo");
     *
     * System.out.format("toString: %s%n", path.toString());
     * System.out.format("getFileName: %s%n", path.getFileName());
     * System.out.format("getName(0): %s%n", path.getName(0));
     * System.out.format("getNameCount: %d%n", path.getNameCount());
     * System.out.format("subpath(0,2): %s%n", path.subpath(0,2));
     * System.out.format("getParent: %s%n", path.getParent());
     * System.out.format("getRoot: %s%n", path.getRoot());
     */

    /**
     * Removing Redundancies From a Path
     * Many file systems use "." notation to denote the current directory and ".." to denote the parent directory. You might
     * have a situation where a Path contains redundant directory information. Perhaps a server is configured to save its log
     * files in the /dir/logs/. directory, and you want to delete the trailing "/." notation from the path.
     *
     * The following examples both include redundancies:
     *
     * /home/./joe/foo
     * /home/sally/../joe/foo
     * The normalize() method removes any redundant elements, which includes any "." or "directory/.." occurrences. Both of
     * the preceding examples normalize to /home/joe/foo.
     *
     * It is important to note that normalize does not check at the file system when it cleans up a path. It is a purely
     * syntactic operation. In the second example, if sally were a symbolic link, removing sally/.. might result in a Path
     * that no longer locates the intended file.
     *
     * To clean up a path while ensuring that the result locates the correct file, you can use the toRealPath() method.
     * This method is described in the next section.
     */

    /**
     * Converting a Path
     * You can use three methods to convert the Path. If you need to convert the path to a string that can be opened from a
     * browser, you can use toUri(). For example:
     *
     * Path p1 = Paths.get("/home/logfile");
     *
     * System.out.format("%s%n", p1.toUri());
     * Running this code produces the following result:
     *
     * file:///home/logfile
     * The toAbsolutePath() method converts a path to an absolute path. If the passed-in path is already absolute, it returns
     * the same Path object. The toAbsolutePath() method can be very helpful when processing user-entered file names.
     * For example:
     *
     * public class FileTest {
     *     public static void main(String[] args) {
     *
     *         if (args.length < 1) {
     *             System.out.println("usage: FileTest file");
     *             System.exit(-1);
     *         }
     *
     *         // Converts the input string to a Path object.
     *         Path inputPath = Paths.get(args[0]);
     *
     *         // Converts the input Path
     *         // to an absolute path.
     *         // Generally, this means prepending
     *         // the current working
     *         // directory.  If this example
     *         // were called like this:
     *         //     java FileTest foo
     *         // the getRoot and getParent methods
     *         // would return null
     *         // on the original "inputPath"
     *         // instance.  Invoking getRoot and
     *         // getParent on the "fullPath"
     *         // instance returns expected values.
     *         Path fullPath = inputPath.toAbsolutePath();
     *     }
     * }
     * The toAbsolutePath() method converts the user input and returns a Path that returns useful values when queried.
     * The file does not need to exist for this method to work.
     *
     * The toRealPath() method returns the real path of an existing file. This method performs several operations in one:
     *
     * If true is passed to this method and the file system supports symbolic links, this method resolves any symbolic links
     * in the path.
     * If the path is relative, it returns an absolute path.
     * If the path contains any redundant elements, it returns a path with those elements removed.
     * This method throws an exception if the file does not exist or cannot be accessed. You can catch the exception when you
     * want to handle any of these cases. For example:
     *
     * try {
     *     Path fp = path.toRealPath();
     * } catch (NoSuchFileException x) {
     *     System.err.format("%s: no such" + " file or directory%n", path);
     *     // Logic for case when file doesn't exist.
     * } catch (IOException x) {
     *     System.err.format("%s%n", x);
     *     // Logic for other sort of file error.
     * }
     */

    /**
     * Joining Two Paths
     * You can combine paths by using the resolve() method. You pass in a partial path , which is a path that does not include a
     * root element, and that partial path is appended to the original path.
     *
     * For example, consider the following code snippet:
     *
     * // Solaris
     * Path p1 = Paths.get("/home/joe/foo");
     *
     * // Result is /home/joe/foo/bar
     * System.out.format("%s%n", p1.resolve("bar"));
     * or
     *
     * // Microsoft Windows
     * Path p1 = Paths.get("C:\\home\\joe\\foo");
     *
     * // Result is C:\home\joe\foo\bar
     * System.out.format("%s%n", p1.resolve("bar"));
     * Passing an absolute path to the resolve() method returns the passed-in path:
     *
     * // Result is /home/joe
     * Paths.get("foo").resolve("/home/joe");
     */

    /**
     * Creating a Path Between Two Paths
     * A common requirement when you are writing file I/O code is the capability to construct a path from one location in the
     * file system to another location. You can meet this using the relativize() method. This method constructs a path
     * originating from the original path and ending at the location specified by the passed-in path. The new path is relative
     * to the original path.
     *
     * For example, consider two relative paths defined as joe and sally:
     *
     * Path p1 = Paths.get("joe");
     * Path p2 = Paths.get("sally");
     * In the absence of any other information, it is assumed that joe and sally are siblings, meaning nodes that reside at
     * the same level in the tree structure. To navigate from joe to sally, you would expect to first navigate one level up
     * to the parent node and then down to sally:
     *
     * // Result is ../sally
     * Path p1_to_p2 = p1.relativize(p2);
     *
     * // Result is ../joe
     * Path p2_to_p1 = p2.relativize(p1);
     * Consider a slightly more complicated example:
     *
     * Path p1 = Paths.get("home");
     * Path p3 = Paths.get("home/sally/bar");
     *
     * // Result is sally/bar
     * Path p1_to_p3 = p1.relativize(p3);
     *
     * // Result is ../..
     * Path p3_to_p1 = p3.relativize(p1);
     * In this example, the two paths share the same node, home. To navigate from home to bar, you first navigate one level
     * down to sally and then one more level down to bar. Navigating from bar to home requires moving up two levels.
     *
     * A relative path cannot be constructed if only one of the paths includes a root element. If both paths include a root
     * element, the capability to construct a relative path is system dependent.
     *
     * The recursive Copy example uses the relativize() and resolve methods.
     */

    /**
     * Comparing Two Paths
     * The Path interface supports equals(), enabling you to test two paths for equality. The startsWith() and endsWith()
     * methods enable you to test whether a path begins or ends with a particular string. These methods are easy to use.
     * For example:
     *
     * Path path = ...;
     * Path otherPath = ...;
     * Path beginning = Paths.get("/home");
     * Path ending = Paths.get("foo");
     *
     * if (path.equals(otherPath)) {
     *     // equality logic here
     * } else if (path.startsWith(beginning)) {
     *     // path begins with "/home"
     * } else if (path.endsWith(ending)) {
     *     // path ends with "foo"
     * }
     * The Path interface extends the Iterable interface. The iterator() method returns an object that enables you to iterate
     * over the name elements in the path. The first element returned is that closest to the root in the directory tree.
     * The following code snippet iterates over a path, printing each name element:
     *
     * Path path = ...;
     * for (Path name: path) {
     *     System.out.println(name);
     * }
     * The Path interface also extends the Comparable interface. You can compare Path objects by using compareTo() which is
     * useful for sorting.
     *
     * You can also put Path objects into a Collection. See the Collections tutorial for more information about this powerful
     * feature.
     *
     * When you want to verify that two Path objects locate the same file, you can use the isSameFile() method from the Files
     * class, as described in the section Checking Whether Two Paths Locate the Same File.
     */

    /**
     * Default File System
     * To retrieve the default file system, use the getDefault() method of the FileSystems factory class. Typically, this
     * FileSystems method (note the plural) is chained to one of the FileSystem methods (note the singular), as follows:
     *
     * PathMatcher matcher =
     *     FileSystems.getDefault().getPathMatcher("glob:*.*");
     * A Path instance is always bound to a file system. If no file system is provided when a path is created, then the
     * default file system is used.
     *
     * Path String Separator
     * The path separator for POSIX file systems is the forward slash, /, and for Microsoft Windows is the backslash, \. Other
     * file systems might use other delimiters. To retrieve the Path separator for the default file system, you can use one
     * of the following approaches:
     *
     * String separator = File.separator;
     * String separator = FileSystems.getDefault().getSeparator();
     * The getSeparator() method is also used to retrieve the path separator for any available file system.
     */

    /**
     * File Stores
     * A file system has one or more file stores to hold its files and directories. The file store represents the underlying
     * storage device. In UNIX operating systems, each mounted file system is represented by a file store. In Microsoft
     * Windows, each volume is represented by a file store.
     *
     * To retrieve a list of all the file stores for the file system, you can use the getFileStores() method. This method
     * returns an Iterable, which allows you to use the enhanced for statement to iterate over all the root directories.
     *
     * FileSystem fileSystem = FileSystems.getDefault();
     * for (FileStore store: fileSystem.getFileStores()) {
     *     System.out.println(store.name() + " - " + store.type());
     * }
     * On a Windows machine, you will get this kind of result.
     *
     * Windows - NTFS
     * Data - NTFS
     * Video - NTFS
     * Transfer - Fat32
     * If you need to access the drive letters, you can use the following code. Remember that some drive letters may be used
     * without the drive been mounted. The following code checks if every drive letters is readable.
     *
     * for (Path directory : fileSystem.getRootDirectories()) {
     *     boolean readable = Files.isReadable(directory);
     *     System.out.println("directory = " + directory + " - " + readable);
     * }
     * Running the previous code on Windows will give a result similar to this one.
     *
     * directory = C:\ - true
     * directory = D:\ - true
     * directory = E:\ - true
     * directory = F:\ - false
     * directory = G:\ - false
     */

}
